package com.apobates.forum.utils;

import java.util.Map;
import java.util.Optional;
import java.util.function.Supplier;

/**
 * 提示消息
 *
 * @author xiaofanku
 * @since 20200512
 */
public final class TipMessage {
    /**
     * 消息内容
     */
    private final String message;
    /**
     * 消息类型
     */
    private final String level;
    /**
     * 绑定的输入元素name
     */
    private final String input;
    
    public TipMessage(String message) {
        this.level = TipMessageLevelEnum.ERR.getLevel();
        this.message = message;
        this.input = null;
    }
    
    public TipMessage(String message, TipMessageLevelEnum level) {
        this.message = message;
        this.level = level.getLevel();
        this.input = null;
    }
    
    public TipMessage(String message, TipMessageLevelEnum level, String input) {
        this.message = message;
        this.level = level.getLevel();
        this.input = input;
    }
    
    public TipMessage(String message, String level) {
        this.message = message;
        this.level = level;
        this.input = null;
    }
    
    public TipMessage(String message, String level, String input) {
        this.message = message;
        this.level = level;
        this.input = input;
    }
    
    // GET/SET
    public String getMessage() {
        return message;
    }
    
    public String getLevel() {
        return level;
    }
    
    public String getInput() {
        return input;
    }
    
    public String toJsonString() {
        return Commons.toJson(this);
    }
    
    public String toJsonString(Map<String, String> extOutputParames) {
        Map<String, String> nativeMap = toMap();
        return Commons.toJson(Commons.mergeMap(nativeMap, extOutputParames, (oldValue, newValue)-> oldValue));
    }
    
    public Map<String,String> toMap(){
        return Map.ofEntries(Map.entry("message", getMessage()), Map.entry("level", getLevel()), Map.entry("input", getInput()));
    }
    
    public static TipMessage ofError(String message) {
        return new TipMessage(message, TipMessageLevelEnum.ERR, "");
    }
    
    public static TipMessage ofError(String message, String inputEle) {
        return new TipMessage(message, TipMessageLevelEnum.ERR, inputEle);
    }
    
    public static TipMessage ofSuccess(String message) {
        return new TipMessage(message, TipMessageLevelEnum.ACC);
    }
    
    public static TipMessage ofSuccess(String message, String url) {
        return new TipMessage(message, TipMessageLevelEnum.ACC, url);
    }
    
    public static class Builder{
        private final boolean condition;
        private final String message;
        
        private Builder(boolean condition) {
            this(condition, null);
        }
        
        private Builder(boolean condition, String message) {
            this.condition = condition;
            this.message = message;
        }
        
        public static Builder take(Supplier<Optional<Boolean>> condition){
            try{
                return new Builder(condition.get().orElse(false));
            }catch(Exception e){
                return new Builder(false, e.getMessage());
            }
        }
        
        public static Builder of(Supplier<Boolean> condition){
            try{
                return new Builder(condition.get());
            }catch(Exception e){
                return new Builder(false, e.getMessage());
            }
        }
        
        /**
         * 若不调用默认为:操作成功
         *
         * @param successMessage 操作成功的内容
         * @return
         */
        public Builder success(String successMessage){
            if(!isCondition()){
                return this;
            }
            return new Builder(isCondition(), successMessage);
        }
        
        /**
         * 生成TipMessage
         *
         * @param errorMessage 操作失败的内容
         * @return
         */
        public TipMessage error(String errorMessage){
            return isCondition()?TipMessage.ofSuccess(Optional.ofNullable(getMessage()).orElse("操作成功")):TipMessage.ofError(Optional.ofNullable(getMessage()).orElse(errorMessage));
        }
        
        public boolean isCondition() {
            return condition;
        }
        
        public String getMessage() {
            return message;
        }
    }
}